package poker;

import static org.junit.Assert.*;


import java.lang.reflect.Field;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.util.*;


import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.Random;

public class PokerTest 
{
    private Random gen = new Random();
    private Card card;
    private Deck deck;
    private Hand hand;
    private Hand hand2;
    private Human human;
    private Bot bot;
    private Table table;
	
    @Before
    public void setUp() throws Exception 
	{
        deck = new Deck();
        hand = new Hand();
    }
    @Test(timeout=10)
    public void testShufflingTime() 
	{
        deck.shuffle();
    }   
    @Test(expected=PokerException.class)
    public void cardException() throws PokerException 
	{
    	short r=14,c=0;
        card = new Card(c,r);
    }   
    @Test(expected=PokerException.class)
    public void tableException() throws PokerException 
	{
        table = new Table(3,4,null,1000,10);
    }  
    @Test
    public void testDrawCard() 
	{
        hand.cardPick(deck);
        int rank = 0;
        int suit = 5;
        try 
		{
            suit = hand.getCard(0).getSuit();
        } 
        catch (PokerException e) 
		{
            e.printStackTrace();
        }
        try 
        {
            rank = hand.getCard(0).getRank();
        } 
        catch (PokerException e) 
		{
            e.printStackTrace();
        }
        assertFalse("Illegal card found!", deck.findCard(suit,rank));
    }
    @Test
    public void WhenComparingTwoEqualStraights_ExpectEquality()
    {
    	hand2 = new Hand();
    	int i=0,s=-1,r=-1;
    	//hand = flush royal straight of spades
    	while(i<5)
    	{
    		hand.cardPick(deck);
    		try
    		{
    			s = hand.getCard(i).getSuit();
    			r = hand.getCard(i).getRank();
    		}
    		catch(Exception ex)
    		{

    		}
    		if((s==0)&&((r==12)||(r==11)||(r==10)||(r==9)||(r==8)))
    		{
    			i++;
    		}
    		else
    		{
    			hand.cardRemove(i);
    		}
    	}
    	deck = new Deck();
    	i = 0;
    	//hand2 = flush royal straight of hearts
    	while(i<5)
    	{
    		hand2.cardPick(deck);
    		try
    		{
    			s = hand2.getCard(i).getSuit();
    			r = hand2.getCard(i).getRank();
    		}
    		catch(Exception ex)
    		{

    		}
    		if((s==1)&&((r==12)||(r==11)||(r==10)||(r==9)||(r==8)))
    		{
    			i++;
    		}
    		else
    		{
    			hand2.cardRemove(i);
    		}
    	}
    	hand.evaluate();
    	hand2.evaluate();
    	assertEquals(0,hand.compareTo(hand2));
    }
    @Test
    public void WhenComparingTwoInequalStraights_ExpectInequality()
    {
    	hand2 = new Hand();
    	int i=0,s=-1,r=-1;
    	//hand = flush royal straight of spades
    	while(i<5)
    	{
    		hand.cardPick(deck);
    		try
    		{
    			s = hand.getCard(i).getSuit();
    			r = hand.getCard(i).getRank();
    		}
    		catch(Exception ex)
    		{

    		}
    		if((s==0)&&((r==12)||(r==11)||(r==10)||(r==9)||(r==8)))
    		{
    			i++;
    		}
    		else
    		{
    			hand.cardRemove(i);
    		}
    	}
    	deck = new Deck();
    	i = 0;
    	//hand2 = weaker flush royal straight of hearts
    	while(i<5)
    	{
    		hand2.cardPick(deck);
    		try
    		{
    			s = hand2.getCard(i).getSuit();
    			r = hand2.getCard(i).getRank();
    		}
    		catch(Exception ex)
    		{

    		}
    		if((s==1)&&((r==11)||(r==10)||(r==9)||(r==8)||(r==7)))
    		{
    			i++;
    		}
    		else
    		{
    			hand2.cardRemove(i);
    		}
    	}
    	hand.evaluate();
    	hand2.evaluate();
    	assertEquals(1,hand.compareTo(hand2));
    }
    @Test
    public void WhenPlayersDontHaveChips_ExpectThemBeingRemoved() throws PokerException
    {
        Table instance = new Table(3,0,null,0,10);
        Class<?> table = instance.getClass();

        Method methods[] = table.getDeclaredMethods();       

    	Field fields[] = table.getDeclaredFields();
    	fields[0].setAccessible(true);
    	Field field = fields[0];
    	try
    	{    
    		ArrayList<Player> play = (ArrayList<Player>) field.get(instance);
    		play.get(0).receiveChips(50);
    		methods[0].invoke(instance);  
    		
    		assertEquals(1,play.size());
    	}
    	catch(Exception e)
    	{
    		e.printStackTrace();
    	}
    	
    }
    @Test
    public void WhenOnePlayerIsBidder_ExpectHavingWinner() throws PokerException
    {
        Table instance = new Table(2,0,null,0,10);
        Class<?> table = instance.getClass();

        Method methods[] = table.getDeclaredMethods();       

    	Field fields[] = table.getDeclaredFields();
    	fields[0].setAccessible(true);
    	Field field = fields[0];
    	try
    	{    
    		ArrayList<Player> play = (ArrayList<Player>) field.get(instance);
    		play.get(0).receiveChips(50);
    		methods[0].invoke(instance);  
    		
    		assertEquals(1,play.get(0).getWins());
    	}
    	catch(Exception e)
    	{
    		e.printStackTrace();
    	}
    	
    }
    @Test
    public void WhenGameIsOver_ExpectNoChipsVanished() throws PokerException
    {
        Table instance = new Table(2,0,null,500,10);
        Class<?> table = instance.getClass();

        Method methods[] = table.getDeclaredMethods();       

    	Field fields[] = table.getDeclaredFields();
    	fields[0].setAccessible(true);
    	Field field = fields[0];
    	
    	fields[5].setAccessible(true);
    	Field field1 = fields[5];
  
    	try
    	{    
    		ArrayList<Player> play = (ArrayList<Player>) field.get(instance);
    		int pot = (int) field1.get(instance);
    		
    		methods[0].invoke(instance);  
    		
    		boolean isMore;
    		
    		if((pot + play.get(0).getChips()) >= 990)
    		{
    			isMore = true;
    		}
    		else
    		{
    			isMore = false;
    		}
    		
    		assertEquals(true,isMore);
    	}
    	catch(Exception e)
    	{
    		e.printStackTrace();
    	}
    	
    }
	@After
    public void tearDown() throws Exception 
	{
        deck = null;
        hand = null;
    }
   
}

